package com.zhou.JavaAndroidFirm.widget;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.FrameLayout;

/**
 * @author Administrator
 * @date 2018/8/16 0016
 * @des
 */
public class PullBackLayout extends FrameLayout {
    @Nullable
    private Callback callback;
    private ViewDragHelper dragger;// http://blog.csdn.net/lmj623565791/article/details/46858663
    private final int minimumFlingVelocity;

    public PullBackLayout(@NonNull Context context) {
        this(context, null);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        try {
            return dragger.shouldInterceptTouchEvent(ev);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        try {
            dragger.processTouchEvent(event);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public PullBackLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public PullBackLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        dragger = ViewDragHelper.create(this, 1f / 8f, new ViewDragCallback());// 1f / 8f是敏感度参数参数越大越敏感
        minimumFlingVelocity = ViewConfiguration.get(context).getScaledMinimumFlingVelocity();
    }

    public void setCallback(Callback Callback) {
        this.callback = Callback;

    }

    private class ViewDragCallback extends ViewDragHelper.Callback {


        /**
         * tryCaptureView如何返回ture则表示可以捕获该view，你可以根据传入的第一个view参数决定哪些可以捕获
         *
         * @param child
         * @param pointerId
         * @return
         */
        @Override
        public boolean tryCaptureView(@NonNull View child, int pointerId) {
            return true;//全部捕获
        }

        /**
         * clampViewPositionHorizontal,clampViewPositionVertical可以在该方法中对child移动的边界进行控制，
         * left , top 分别为即将移动到的位置
         *
         * @param child
         * @param left
         * @param dx
         * @return
         */
        @Override
        public int clampViewPositionHorizontal(@NonNull View child, int left, int dx) {
            return 0;
        }


        @Override
        public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
            return Math.max(0, top);
        }

        /**
         * 如果子View不消耗事件，那么整个手势（DOWN-MOVE*-UP）都是直接进入onTouchEvent，
         * 在onTouchEvent的DOWN的时候就确定了captureView。
         * 如果消耗事件，那么就会先走onInterceptTouchEvent方法，
         * 判断是否可以捕获，
         * 而在判断的过程中会去判断另外两个回调的方法：
         * getViewHorizontalDragRange和getViewVerticalDragRange，
         * 只有这两个方法返回大于0的值才能正常的捕获。
         * 方法的返回值应当是该childView横向或者纵向的移动的范围
         * 当前如果只需要一个方向移动，可以只复写一个。
         *
         * @param child
         * @return
         */
        @Override
        public int getViewHorizontalDragRange(@NonNull View child) {
            return 0;
        }

        @Override
        public int getViewVerticalDragRange(@NonNull View child) {
            return getHeight();
        }


        /**
         * 当captureview被捕获时回调
         *
         * @param capturedChild
         * @param activePointerId
         */
        @Override
        public void onViewCaptured(@NonNull View capturedChild, int activePointerId) {
            if (callback != null) {
                callback.onPullStart();
            }
        }

        /**
         * 当captureview的位置发生改变时回调
         *
         * @param changedView
         * @param left
         * @param top
         * @param dx
         * @param dy
         */
        @Override
        public void onViewPositionChanged(@NonNull View changedView, int left, int top, int dx, int dy) {
            if (callback != null) {
                callback.onPull((float) top / (float) getHeight());
            }
        }


        /**
         * 当captureview的拖拽被释放的时回调
         *
         * @param releasedChild
         * @param xvel
         * @param yvel
         */
        @Override
        public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
            int solp = yvel > minimumFlingVelocity ? getHeight() / 6 : getHeight() / 3;
            if (releasedChild.getTop() > solp) {
                if (callback != null) {
                    callback.onPullComplete();
                } else {
                    if (callback != null) {
                        callback.onPullCancel();
                    }

                    dragger.settleCapturedViewAt(0, 0);
                    invalidate();
                }
            }
        }
    }


    public interface Callback {
        void onPullStart();

        void onPull(float progress);

        void onPullCancel();

        void onPullComplete();
    }
}
